"""项目级日志配置模块。

提供统一的日志初始化入口，支持同时输出到终端、文件以及 SQLite
数据库中的 `run_log` 表。数据库写入便于在 UI 中或离线复盘时查看
运行轨迹。
"""
from __future__ import annotations

import logging
import sqlite3
import sys
from datetime import datetime
from logging import Handler, LogRecord
from pathlib import Path
from typing import Optional

from .config import get_config
from .db import db_session

_LOGGER_NAME = "app.logging"
_IS_CONFIGURED = False
_CONVERSATION_LOGGER_NAME = "app.conversation"
_CONVERSATION_HANDLER: Optional[Handler] = None
_CONVERSATION_LOGFILE: Optional[Path] = None

logging.getLogger("watchdog").setLevel(logging.WARNING)

class DatabaseLogHandler(Handler):
    """将日志写入 SQLite `run_log` 表的自定义 Handler。"""

    def emit(self, record: LogRecord) -> None:  # noqa: D401 - 标准 logging 接口
        try:
            message = self.format(record)
            stage = getattr(record, "stage", None)
            ts = datetime.utcnow().isoformat(timespec="microseconds") + "Z"
            with db_session() as conn:
                conn.execute(
                    "INSERT INTO run_log (ts, stage, level, msg) VALUES (?, ?, ?, ?)",
                    (ts, stage, record.levelname, message),
                )
        except sqlite3.OperationalError as exc:
            # 表不存在时直接跳过，避免首次初始化阶段报错
            if "no such table" not in str(exc).lower():
                self.handleError(record)
        except Exception:
            self.handleError(record)


def _build_formatter() -> logging.Formatter:
    return logging.Formatter("%(asctime)s %(levelname)s %(name)s - %(message)s")


def setup_logging(
    *,
    level: Optional[int] = None,
    console_level: Optional[int] = None,
    file_level: Optional[int] = None,
    db_level: Optional[int] = None,
) -> logging.Logger:
    """配置根 logger。重复调用时将复用已存在的配置。"""

    global _IS_CONFIGURED
    if _IS_CONFIGURED:
        return logging.getLogger()

    cfg = get_config()
    resolved_level = logging.DEBUG
    level_name = getattr(cfg, "log_level", None)
    if isinstance(level_name, str) and level_name.strip():
        normalized_name = level_name.strip()
        try:
            resolved_level = getattr(logging, normalized_name.upper())
        except AttributeError:
            try:
                resolved_level = int(normalized_name)
            except (TypeError, ValueError):
                logging.getLogger(_LOGGER_NAME).warning(
                    "非法的日志级别 %s，回退到 DEBUG", normalized_name
                )
                resolved_level = logging.DEBUG
    elif level is not None:
        resolved_level = int(level)

    timestamp = datetime.now().strftime("%Y%m%d_%H%M")
    log_dir: Path = cfg.data_paths.root / "logs"
    log_dir.mkdir(parents=True, exist_ok=True)
    logfile = log_dir / f"app_{timestamp}.log"
    conversation_logfile = log_dir / f"agent_{timestamp}.log"

    root = logging.getLogger()
    root.setLevel(resolved_level)
    root.handlers.clear()

    formatter = _build_formatter()

    console_handler = logging.StreamHandler(stream=sys.stdout)
    console_handler.setLevel(console_level if console_level is not None else resolved_level)
    console_handler.setFormatter(formatter)
    root.addHandler(console_handler)

    file_handler = logging.FileHandler(logfile, encoding="utf-8")
    file_handler.setLevel(file_level if file_level is not None else resolved_level)
    file_handler.setFormatter(formatter)
    root.addHandler(file_handler)

    db_handler = DatabaseLogHandler(level=db_level if db_level is not None else resolved_level)
    db_handler.setFormatter(formatter)
    root.addHandler(db_handler)

    _IS_CONFIGURED = True

    root.info(
        "日志系统初始化完成",
        extra={
            "stage": "config",
            "config": {
                "tushare_token_set": bool(cfg.tushare_token),
                "force_refresh": cfg.force_refresh,
                "data_root": str(cfg.data_paths.root),
                "logfile": str(logfile),
                "log_level": getattr(cfg, "log_level", resolved_level),
            },
        },
    )
    conversation_logger = logging.getLogger(_CONVERSATION_LOGGER_NAME)
    conversation_logger.setLevel(resolved_level)
    conversation_logger.handlers.clear()
    conversation_logger.propagate = False
    conv_handler = logging.FileHandler(conversation_logfile, encoding="utf-8")
    conv_handler.setLevel(resolved_level)
    conv_handler.setFormatter(formatter)
    conversation_logger.addHandler(conv_handler)

    global _CONVERSATION_HANDLER, _CONVERSATION_LOGFILE
    _CONVERSATION_HANDLER = conv_handler
    _CONVERSATION_LOGFILE = conversation_logfile

    return root


def get_logger(name: Optional[str] = None) -> logging.Logger:
    """返回指定名称的 logger，确保全局配置已就绪。"""

    setup_logging()
    logger = logging.getLogger(name)
    # Quiet noisy third-party loggers when default level is DEBUG
    logging.getLogger("urllib3").setLevel(logging.WARNING)
    logging.getLogger("urllib3.connectionpool").setLevel(logging.WARNING)
    logging.getLogger("requests.packages.urllib3").setLevel(logging.WARNING)
    return logger


def get_conversation_logger() -> logging.Logger:
    """Return conversation logger for agent dialogues."""

    setup_logging()
    logger = logging.getLogger(_CONVERSATION_LOGGER_NAME)
    logger.propagate = False
    return logger


# 默认在模块导入时完成配置，适配现有调用方式。
setup_logging()
